﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenNETCF.MTConnect;
using Okuma.CLDATAPI.DataAPI;
using System.Windows.Forms;
using OpenNETCF.IoC;

namespace Okuma
{
    public class MachineDevice : HostedDeviceBase
    {
        private CMachine m_machine;
        private CurrentAlarm m_currentAlarm;

        private string m_name;
        private string m_serialNumber;
        private List<IHostedComponent> m_components;

        private ILogService Log { get; set; }

        internal MachineDevice(IHostedAdapter adapter, OkumaConfiguration configuration)
            : base(adapter)
        {
            try
            {
                Log = RootWorkItem.Services.Get<ILogService>();

                // the name here is used only for logging
                m_machine = new CMachine("Solution Machine");

                // you *must* Init the machine before doing anything else
                m_machine.Init();

                // build up the machine
                m_machine.SetSubSystem(configuration.SubSystem);

                // build up the components
                CreateComponents(configuration);

                m_name = THINCProvider.MachineName;
                m_serialNumber = THINCProvider.MachineSerialNumber;

                Available = "AVAILABLE";
            }
            catch (Exception ex)
            {
                Available = "UNAVAILABLE";

                MessageBox.Show(ex.Message);
            }
        }

        private void CreateComponents(OkumaConfiguration configuration)
        {
            m_components = new List<IHostedComponent>();
            m_currentAlarm = new CurrentAlarm();
            m_components.Add(m_currentAlarm);

            var axes = new HostedAxes();

            if (configuration.Axes.Length > 0)
            {
                axes.Components.AddRange(configuration.Axes);
            }
            if (configuration.Spindle != null)
            {
                axes.Components.Add(configuration.Spindle);
            }

            if (axes.Components.Count > 0)
            {
                m_components.Add(axes);
            }

            if (configuration.Program != null)
            {
                var controller = new Controller(configuration.Program);
                m_components.Add(controller);
            }

            if (configuration.Workpiece != null)
            {
                m_components.Add(configuration.Workpiece);
            }
        }

        public override IEnumerable<IHostedComponent> Components
        {
            get { return m_components; }
        }

        public override string Name
        {
            get { return m_name; }
        }

        public override string SerialNumber
        {
            get { return m_serialNumber; }
        }

        public override string Manufacturer
        {
            get { return "Okuma"; }
        }

        private string m_available;

        [EventDataItem(
            ItemType = DataItemType.AVAILABILITY)]
        public string Available
        {
            get { return m_available; }
            set
            {
                if (m_available == value) return;
                m_available = value;
                RaisePropertyChanged("Available");
            }
        }

        [EventDataItem(
            ItemType = DataItemType.EXECUTION)]
        public string ExecutionMode
        {
            // TODO: convert the result to an MTCONNECT-ised EXECUTION string
            get 
            {
                return m_machine.GetExecutionMode().ToString();
            }
        }

        [EventDataItem]
        public string MachineSelection
        {
            get 
            {
                return m_machine.GetMachineSelection().ToString();
            }
        }

        [EventDataItem]
        public string OperationMode
        {
            get
            {
                return m_machine.GetOperationMode().ToString();
            }
        }

        [SampleDataItem(UnitValues.Second)]
        public double CuttingTime
        {
            get 
            {
                return m_machine.GetHourMeterCount(CLDATAPI.Enumerations.HourMeterEnum.CuttingTime);
            }
        }

        [SampleDataItem(UnitValues.Second)]
        public double NCRunningTime
        {
            get
            {
                return m_machine.GetHourMeterCount(CLDATAPI.Enumerations.HourMeterEnum.NCRunningTime);
            }
        }

        [SampleDataItem(UnitValues.Second)]
        public double PowerOnTime
        {
            get
            {
                return m_machine.GetHourMeterCount(CLDATAPI.Enumerations.HourMeterEnum.PowerOnTime);
            }
        }

        internal void OnRefreshTick()
        {
            // Refresh current alarms
            m_currentAlarm.Alarm = m_machine.GetCurrentAlarm();
        }
    }
}
